package com.ac.api.production_order.service.impl;

import com.ac.api.base.Result;
import com.ac.api.equipment.entity.Equipment;
import com.ac.api.equipment.service.EquipmentService;
import com.ac.api.process_history.entity.ProcessHistory;
import com.ac.api.process_history.service.ProcessHistoryService;
import com.ac.api.process_line.entity.ProcessLine;
import com.ac.api.process_line.service.ProcessLineService;
import com.ac.api.process_task.entity.ProcessTask;
import com.ac.api.process_task.service.ProcessTaskService;
import com.ac.api.production_order.entity.noEquitmentException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ac.api.production_order.entity.ProductionOrder;
import com.ac.api.production_order.dao.ProductionOrderMapper;
import com.ac.api.production_order.service.ProductionOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 生产订单主表 服务实现类
 * </p>
 *
 * @author dc
 * @since 2025-06-11
 */
@Service
public class ProductionOrderServiceImpl extends ServiceImpl<ProductionOrderMapper, ProductionOrder> implements ProductionOrderService {
    @Autowired
    private ProcessLineService processLineService;
    @Autowired
    private ProcessTaskService processTaskService;
    @Autowired
    private EquipmentService equipmentService;
    @Autowired
    private ProcessHistoryService processHistoryService;
    @Override
    public List<ProductionOrder> list(ProductionOrder example) {
        return this.list(buildWrapper(example));
    }

    @Override
    public IPage<ProductionOrder> page(ProductionOrder example, IPage page) {
        return this.page(page,buildWrapper(example));
    }

    @Override
    public String complete(Integer id) {
        ProductionOrder productionOrder = this.getById(id);
        if (Objects.equals(productionOrder.getCount()-productionOrder.getLowcount(), productionOrder.getQuantity())){
            ProcessLine processLine = processLineService.getById(productionOrder.getOrderBylineId());
            this.update(new ProductionOrder().setStatus("完成").setPriority("0").setOrderBylineId( null)
                    .setUpdatedAt(null),new QueryWrapper<ProductionOrder>().eq("order_id",id));
            processLineService.updateById(processLine
                    .setStatus("待生产")
                    .setUpdatedAt(LocalDateTime.now())
                    .setEndTime(LocalDateTime.now())
                    .setStartTime(null));
            for (ProcessTask processTask : processTaskService.list(new QueryWrapper<ProcessTask>().eq("Line_id",processLine.getLineId())))
            {
                processTaskService.updateById(processTask
                        .setStatus("待生产")
                        .setUpdatedAt(LocalDateTime.now())
                );//将生产线下属生产区停止
                for (Equipment equipment : equipmentService.list(new QueryWrapper<Equipment>().eq("production_task_id",processTask.getTaskId())))
                {
                    equipmentService.updateById(equipment
                            .setProductionTaskId(processTask.getTaskId())
                            .setUpdatedAt(LocalDateTime.now())
                            .setStatus("停机")
                    );
                }
            }
            processHistoryService.addHistory(id, processLine.getLineId(),"生产完成记录");//为挤停的生产工序生成历史记录
            return "订单完成";
        }
        return "订单完成交付失败";
    }


    @Override
    @Transactional
    public String setPriorityUrgent(Integer id) {
        ProductionOrder productionOrder = this.getById(id);

        if(productionOrder.getStatus().equals("待排产")){//
            ProcessLine processline =processLineService.getOne(new QueryWrapper<ProcessLine>().eq("status","待生产")
                    .eq("product_model", productionOrder.getProductModel()));//获取对应产品型号的闲置生产线

            if (processline!=null){//有对应型号的空余生产线
                this.updateById(new ProductionOrder().setOrderId(id)
                                .setOrderBylineId(processline.getLineId())//设置对应生产线到订单
                        .setStatus("生产中")//设置为生产中
                        .setPriority("1")//设置为加急
                         );

                processLineService.update(new ProcessLine().setStatus("加急中")
                        .setEndTime(null)
                        .setStartTime(LocalDateTime.now()),new QueryWrapper<ProcessLine>().eq("line_id",processline.getLineId()));
                return "订单设置加急成功";
            }

            //无对应型号的空余生产线，挤一条生产线出来
           else{
               processline=processLineService.getOne(new QueryWrapper<ProcessLine>()
                       .eq("status","生产中")
                       .eq("product_model", productionOrder.getProductModel())
                       .orderByDesc("end_time"));//获取生产中的对应生产型号的endTime结束时间最迟的的生产线
                if(processline==null){//无对应型号的生产线
                    return "订单设置加急失败，无对应空余生产线";
                }
                this.update(new UpdateWrapper<ProductionOrder>()
                        .eq("order_byline_id", processline.getLineId())
                        .set("order_byline_id", null)
                        .set("status", "待排产")
                        .set("priority", "0"));//将找到的结束时间最迟的非加急生产线的对应订单挤停

                for (ProcessTask processTask : processTaskService.list(new QueryWrapper<ProcessTask>().eq("Line_id",processline.getLineId())))
                {
                    processTaskService.updateById(processTask
                            .setStatus("待生产")
                            .setUpdatedAt(LocalDateTime.now())
                    );//将生产线下属生产区停止
                    for (Equipment equipment : equipmentService.list(new QueryWrapper<Equipment>().eq("production_task_id",processTask.getTaskId())))
                    {
                        equipmentService.updateById(equipment
                                .setProductionTaskId(processTask.getTaskId())
                                .setUpdatedAt(LocalDateTime.now())
                                .setStatus("停机")
                        );
                    }
                }

                processHistoryService.addHistory( id,processline.getLineId(),"中断记录");//为挤停的生产工序生成历史记录
                processline.setEndTime(null);
                processline.setStartTime(LocalDateTime.now());
                processline.setStatus("加急中");//切换生产线为加急1状态
                processLineService.updateById(processline);//更新对应生产线状态
                this.updateById(new ProductionOrder().setOrderId(id)
                        .setOrderBylineId(processline.getLineId())//设置对应生产线到加急订单
                        .setStatus("生产中")//设置为生产中
                        .setPriority("1")//设置为加急
                );
                return "订单设置加急成功";
            }
        }

        else if(productionOrder.getStatus().equals("生产中")){//生产中则设置为加紧并分配设备,加入空余设备到生产线生产区
            ProcessLine processline=processLineService.getById(productionOrder.getOrderBylineId());//订单对应生产线
            List<Equipment> list=equipmentService.list(new QueryWrapper<Equipment>()
                    .eq("production_task_id",0));//获取没在干活的设备列表
            List<ProcessTask> processTaskList= processTaskService.list(new QueryWrapper<ProcessTask>()
                    .eq("Line_id",processline.getLineId()));//获取订单对应生产线的工作区列表
            processline.setStatus("加急中");
            processline.setEndTime(null);
            processline.setStartTime(LocalDateTime.now());
            processLineService.updateById(processline);
            this.updateById(new ProductionOrder().setOrderId(id)
                    .setOrderBylineId(processline.getLineId())//设置对应生产线到订单
                    .setStatus("生产中")//设置为生产中
                    .setPriority("1")//设置为加急
            );
            //对应工序区
            for (ProcessTask processTask : processTaskList) {//遍历所有工序区
                for (Equipment e : list) {//在每个工序区中遍历空设备找到合适的设备

                    if (processTask.getProcessName().equals(e.getType())&e.getStatus().equals("运行")) {//设备干的活跟对应工序匹配
                        e.setProductionTaskId(processTask.getTaskId());//将设备设置为某一工序区的设备
                        equipmentService.updateById(e);//更新，相当于每个工序区因加急，均分配一个空设备
                        break;
                    }
                    ;

                }

            }
            return "订单设置加急成功";
        }

        else {
            return "订单设置加急失败";
        }
    }
    //将订单取消加急
    @Override
    @Transactional
    public String cancelPriorityUrgent(Integer id) {
        ProductionOrder productionOrder = this.getById(id);
        if(productionOrder.getPriority().equals("1")){
            this.updateById(productionOrder
                    .setStatus("生产中")
                    .setPriority("0"));
            ProcessLine processline=processLineService.getById(productionOrder.getOrderBylineId());
            processLineService.updateById(processline
                    .setStatus("生产中")
            );
            return "订单取消加急成功";
        }
        else {
            return "订单并不在加急状态";
        }
    }

    @Override
    public List<ProductionOrder> running() {
        return this.list(new QueryWrapper<ProductionOrder>()
                .eq("status", "生产中")
        );
    }

    @Override
    public List<ProductionOrder> getWaitingOrders() {
        return this.list(new QueryWrapper<ProductionOrder>()
                .eq("status", "待排产")
        );
    }

    //将订单移出当前执行的生产线
    @Override
    @Transactional
    public String removeFromLine(Integer id) {
        ProductionOrder productionOrder = this.getById(id);
        productionOrder.setPriority("0");/////
        productionOrder.setStatus("待排产");
        ProcessLine processline=processLineService.getById(productionOrder.getOrderBylineId());
        productionOrder.setOrderBylineId(null);
        this.updateById(productionOrder);

        processHistoryService.addHistory( id,processline.getLineId(),"中断记录");//为挤停的生产工序生成历史记录
        processLineService.updateById(processline
                .setStatus("待生产")
                .setUpdatedAt(LocalDateTime.now())
                .setEndTime(LocalDateTime.now())
                .setStartTime(null)
        );
        for (ProcessTask processTask : processTaskService.list(new QueryWrapper<ProcessTask>().eq("Line_id",processline.getLineId())))
        {
            processTaskService.updateById(processTask
                    .setStatus("待生产")
                    .setUpdatedAt(LocalDateTime.now())
            );//将生产线下属生产区停止
            for (Equipment equipment : equipmentService.list(
                    new QueryWrapper<Equipment>().eq("production_task_id",processTask.getTaskId())))
            {
                LambdaUpdateWrapper<Equipment> wrapper = new LambdaUpdateWrapper<>();
                wrapper.eq(Equipment::getProductionTaskId, processTask.getTaskId())
                        .set(Equipment::getStatus, "停机")
                        .set(Equipment::getUpdatedAt, LocalDateTime.now())
                        .set(Equipment::getProductionTaskId, processTask.getTaskId());

                equipmentService.update(wrapper);
            }
        }
        return "订单移出当前生产线成功";
    }
    //将订单加入指定生产线
    @Override
    @Transactional
    public void addToProduction(Integer id, Integer productionLineId) {
        processLineService.addToProduction(productionLineId,this.getById(id).getEndtime());
        this.updateById(new ProductionOrder()
                .setOrderId(id)
                .setStatus("生产中")
                .setOrderBylineId(productionLineId));

        ProcessLine processline=processLineService.getById(productionLineId);
        for (ProcessTask processTask : processTaskService.list(new QueryWrapper<ProcessTask>().eq("Line_id",processline.getLineId())))
        {
            processTaskService.updateById(processTask
                    .setStatus("生产中")
                    .setUpdatedAt(LocalDateTime.now())
            );//将生产线下属生产区开始生产
            List<Equipment> list = equipmentService.list(new QueryWrapper<Equipment>().eq("production_task_id",processTask.getTaskId()));
            if (list.size()>0){
                for (Equipment equipment : list) {
                    equipmentService.updateById(equipment
                            .setProductionTaskId(processTask.getTaskId())
                            .setUpdatedAt(LocalDateTime.now())
                            .setStatus("运行")
                    );
                }
            }
            else {
                throw new noEquitmentException( "订单加入生产线失败.该生产线"+processTask.getTaskId()+"号生产区没有设备，请添加设备");
            }
        }
    }
    /**
     * 构建查询
     *
     * @param example
     * @return
     */
    private QueryWrapper<ProductionOrder> buildWrapper(ProductionOrder example) {
        QueryWrapper<ProductionOrder> wrapper     = new QueryWrapper<>();
        return wrapper;
    }

}
